/*
 * @(#)ClassificationTypeTransformer.java
 * Date 2013-09-02
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.transformer.xds;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.enterprise.context.ApplicationScoped;

import javax.inject.Inject;

import oasis.names.tc.ebxml_regrep.xsd.rim._3.ClassificationType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.SlotType1;

import org.apache.commons.lang3.StringUtils;

import us.hornerscorners.lamppost.model.common.CodedElement;
import us.hornerscorners.lamppost.model.common.IClassifiableModel;

import us.hornerscorners.lamppost.model.document.Author;
import us.hornerscorners.lamppost.model.document.ClassificationNode;

import us.hornerscorners.lamppost.registry.constant.Metadata;
import us.hornerscorners.lamppost.registry.constant.SlotName;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-09-02
 * @author         Jim Horner
 */
@ApplicationScoped
public class ClassificationTypeTransformer {

    /** Field description */
    @Inject
    private InternationalStringTypeTransformer internationalStringTransformer;

    /** Field description */
    @Inject
    private SlotTypeTransformer slotTransformer;

    /** Field description */
    @Inject
    private VersionInfoTypeTransformer versionInfoTransformer;

    /**
     * Constructs ...
     *
     */
    public ClassificationTypeTransformer() {
        super();
    }

    /**
     * Method description
     *
     *
     * @param schemeMetadata
     * @param model
     *
     * @return
     */
    private ClassificationType transform(Metadata schemeMetadata,
            IClassifiableModel classifiedObject, IClassifiableModel model) {

        ClassificationType result = new ClassificationType();

        result.setId(model.getEntryURN());

        // versioning
        result.setLid(model.getEntryLogicalURN());
        result.setVersionInfo(
            this.versionInfoTransformer.transform(model.getEntryVersion()));

        result.setClassificationScheme(schemeMetadata.getURN());
        result.setClassifiedObject(classifiedObject.getEntryURN());
        result.setObjectType(Metadata.ClassificationObjectType.getURN());

        result.setName(
            this.internationalStringTransformer.transform(model.getDisplayNames()));
        result.setDescription(
            this.internationalStringTransformer.transform(model.getDescriptions()));

        return result;
    }

    /**
     * Method description
     *
     *
     * @param author
     *
     * @return
     */
    public ClassificationType transformAuthor(Metadata authorMetadata,
            IClassifiableModel classifiedObject, Author author) {

        ClassificationType result = transform(authorMetadata, classifiedObject, author);

        List<SlotType1> slots = result.getSlot();

        List<String> authorInstitutions = author.getInstitutions();

        if (authorInstitutions.isEmpty() == false) {

            slots.add(this.slotTransformer.transform(SlotName.AuthorInstitution,
                    authorInstitutions));
        }

        String authorPerson = author.getPerson();

        if (StringUtils.isNotBlank(authorPerson)) {

            slots.add(this.slotTransformer.transform(SlotName.AuthorPerson,
                    authorPerson));
        }

        List<String> authorRoles = author.getRoles();

        if (authorRoles.isEmpty() == false) {

            slots.add(this.slotTransformer.transform(SlotName.AuthorRole, authorRoles));
        }

        List<String> authorSpecialities = author.getSpecialities();

        if (authorSpecialities.isEmpty() == false) {

            slots.add(this.slotTransformer.transform(SlotName.AuthorSpecialty,
                    authorSpecialities));
        }

        List<String> authorTelecommunications = author.getTelecommunications();

        if (authorTelecommunications.isEmpty() == false) {

            slots.add(this.slotTransformer.transform(SlotName.AuthorTelecommunication,
                    authorTelecommunications));
        }

        return result;
    }

    /**
     * Method description
     *
     *
     * @param authors
     *
     * @return
     */
    public Collection<ClassificationType> transformAuthors(Metadata metadata,
            IClassifiableModel classifiedObject, List<Author> authors) {

        List<ClassificationType> result = new ArrayList<>();

        for (Author author : authors) {

            result.add(transformAuthor(metadata, classifiedObject, author));
        }

        return result;
    }

    /**
     * Method description
     *
     *
     * @param classifiedObject
     * @param cnode
     *
     * @return
     */
    public ClassificationType transformClassificationNode(ClassificationNode cnode,
            IClassifiableModel classifiedObject) {

        ClassificationType result = new ClassificationType();

        result.setClassificationNode(cnode.getNodeURN());
        result.setClassifiedObject(classifiedObject.getEntryURN());
        result.setId(cnode.getEntryURN());
        result.setObjectType(Metadata.ClassificationObjectType.getURN());

        return result;
    }

    /**
     * Method description
     *
     *
     * @param code
     *
     * @return
     */
    public ClassificationType transformCodedElement(Metadata schemeMetadata,
            IClassifiableModel classifiedObject, CodedElement code) {

        ClassificationType result = transform(schemeMetadata, classifiedObject, code);

        result.setNodeRepresentation(code.getCode());

        // create slot for codeSystem
        result.getSlot().add(this.slotTransformer.transform(SlotName.CodingScheme,
                code.getCodeSystem()));

        return result;
    }

    /**
     * Method description
     *
     *
     * @param scheme
     * @param codes
     *
     * @return
     */
    public Collection<ClassificationType> transformCodedElements(Metadata scheme,
            IClassifiableModel classifiedObject, List<CodedElement> codes) {

        List<ClassificationType> result = new ArrayList<>();

        for (CodedElement code : codes) {

            result.add(transformCodedElement(scheme, classifiedObject, code));
        }

        return result;
    }
}
